#include <QtCore/QCoreApplication>
#include <QTest>
#include <QtTest\Qttest>
#include <iostream>
#include <qobject.h>
#include <QxtLogger>
#include <QxtBasicFileLoggerEngine>
#include <QxtBasicSTDLoggerEngine>
#include <QDebug>
#include <Entry.h>
#include "Event.h"
#include <EntryManager.h>
#include <Task.h>
#include <FileManager.h>
#include <EntriesManager.h>
#include <Tokeniser.h>
#include <FileManagerStub.h>
#include <EntryStub.h>
using namespace std;
class TokeniserTest:public QObject {
	Q_OBJECT
private:
	private slots:
		void initTestCase() {
			// Called before all unit tests.

			// Initialize the logging engines
			QxtLoggerEngine *fileLogger = new QxtBasicFileLoggerEngine("test.log");
			QxtLoggerEngine *stdoutLogger = new QxtBasicSTDLoggerEngine();

			qxtLog->addLoggerEngine("file", fileLogger);
			qxtLog->addLoggerEngine("stdout", stdoutLogger);

			qxtLog->disableAllLogLevels();

			qxtLog->enableLogLevels("file", QxtLogger::AllLevels);
			qxtLog->enableLogLevels("stdout", QxtLogger::AllLevels);
		}
		void testWordSplit() {
			string textLine;
			getline(cin, textLine);
			vector<string> temp=Tokeniser::splitToWords(textLine);
			for(int i=0; i<temp.size(); i++)
				cout << temp[i] << endl;
		} 
		void testExtractLineNum() {
			string textLine = "delete 5";
			Tokeniser::extractCommand(textLine);
			int lineNum = Tokeniser::extractLineNum(textLine);

			QVERIFY(lineNum == 5);
		}
		void testExtractCommand() {
			string textLine = "add water plants";
			CommonUtils::COMMAND_TYPE command = Tokeniser::extractCommand(textLine);

			QVERIFY(command == CommonUtils::COMMAND_ADD);
		}
		void testExtractKey() {
			string textLine = "go shopping";
			string keywords = Tokeniser::extractKey(textLine);

			QVERIFY(keywords == "go shopping");
		}
		void testIsInString() { //equivalence partitioning
			string onKeyword = " on ";
			string textLine = "add tuition on monday";

			QVERIFY(Tokeniser::isInString(textLine, onKeyword));
            
            string textLine2 = "add hw by monday";
            
            QVERIFY(!Tokeniser::isInString(textLine2, onKeyword));
		}
		void testExtractName() {
			string textLine = "tuition on monday 12:30pm";

			QVERIFY(Tokeniser::extractName(textLine) == "tuition");
		}
		void testExtractTypeToDisplay() { //equivalence partitioning
			string textLine = "add tuition on monday";

			QVERIFY(Tokeniser::extractTypeToDisplay(textLine) == " event ");

			string textLine2 = "add hw by monday";

			QVERIFY(Tokeniser::extractTypeToDisplay(textLine2) == " task ");

			string textLine3 = "add hi";

			QVERIFY(Tokeniser::extractTypeToDisplay(textLine3) == " event "); //by default for no keywords
		}
		void testFormatDate() {  //boundary testing for the accepted patition and equivalence partition
			string date = "31/12/14";
			QDate qdate = Tokeniser::formatDate(date);

			QString qstr = QString::fromStdString(date);
			QDate dateToCompare = QDate::fromString(qstr, "dd/M/yy");
			dateToCompare = dateToCompare.addYears(100);

			QVERIFY(Tokeniser::formatDate(date) == dateToCompare);

			string date2 = "15/12/2014"; //not an accepted format
			QDate qdate2 = Tokeniser::formatDate(date2);

			QString qstr2 = QString::fromStdString(date2);
			QDate dateToCompare2 = QDate::fromString(qstr2, "dd/M/yyyy");

			QVERIFY(Tokeniser::formatDate(date2) != dateToCompare2);

			string date3 = "15/15/14"; //not in range, will not be processed
			QDate qdate3 = Tokeniser::formatDate(date3);

			QString qstr3 = QString::fromStdString(date3);
			QDate dateToCompare3 = QDate::fromString(qstr3, "dd/M/yy");

			qDebug() << qdate3;

			QVERIFY(Tokeniser::formatDate(date3) == dateToCompare3);
		}
		void testFormatTime() { //boundary testing for the accepted patition
			string time = "1230";
			QTime qtime = Tokeniser::formatTime(time);

			QString qstr = QString::fromStdString(time);
			QTime timeToCompare = QTime::fromString(qstr, "hhmm");

			QVERIFY(Tokeniser::formatTime(time) == timeToCompare);

			string time2 = "12.30"; //not the right format
			QTime qtime2 = Tokeniser::formatTime(time2);

			QString qstr2 = QString::fromStdString(time2);
			QTime timeToCompare2 = QTime::fromString(qstr2, "hh.mm");

			QVERIFY(Tokeniser::formatTime(time2) != timeToCompare2);
		}
		void testCheckNumOfKeyword() {
			string textLine = "add cs tutorial on friday from 1600 to 1800";

			QVERIFY(Tokeniser::checkNumOfKeyword(textLine) == 3);
		}
		void testCheckDateOrTime() {  //equivalence partition
			string date = "12/04/14";
			QVERIFY(Tokeniser::checkDateOrTime(date) == "date");

			string time = "12:30pm";
			QVERIFY(Tokeniser::checkDateOrTime(time) == "time");

			string time2 = "12.30";
			QVERIFY(Tokeniser::checkDateOrTime(time2) != "time" && Tokeniser::checkDateOrTime(time2) != "date");

			string date2 = "12.03.14";
			QVERIFY(Tokeniser::checkDateOrTime(date2) != "time" && Tokeniser::checkDateOrTime(date2) != "date");
		}
		void testConvertDateTimeToString() {
			string time = "12/05";

			QVERIFY(Tokeniser::convertDateTimeToString(time) == "12/05/2014");
			system("pause");
		}

};
class EntriesManagerUTest : public QObject{//stubs for FileManager and Entry are used for this test class
	Q_OBJECT;
	EntriesManager* alpha;
private:
	private slots:
		void initTestCase() {
				// Called before all unit tests.

			// Initialize the logging engines
			QxtLoggerEngine *fileLogger = new QxtBasicFileLoggerEngine("test.log");
			QxtLoggerEngine *stdoutLogger = new QxtBasicSTDLoggerEngine();

			qxtLog->addLoggerEngine("file", fileLogger);
			qxtLog->addLoggerEngine("stdout", stdoutLogger);

			qxtLog->disableAllLogLevels();

			qxtLog->enableLogLevels("file", QxtLogger::AllLevels);
			qxtLog->enableLogLevels("stdout", QxtLogger::AllLevels);
			alpha = EntriesManager::getInstance(new FileManagerStub);
		}
		void testGetconflict() {
			for(int i=0; i<10; i++) {
				alpha->addCommand(new EntryStub);//push in 10 entrystubs
			}
			Entry* stub = new EntryStub;
			vector<Entry*> temp = alpha->getConflict(stub);//should return a vector size 0; since entrystub returns false everytime
			QVERIFY(temp.size() == 0);
		}
		void testAdd() {
			//EntriesManager alpha;
			Entry* stub;
			alpha->clearCommand();
			stub = new Event("jack",QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1400","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1300","hhmm"), 0);//1-2
			alpha->addCommand(stub);
			stub = new Event("jack1",QDate::fromString("230114","ddMMyy"),QTime::fromString("1430","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1400","hhmm"), 0);//2-230
			alpha->addCommand(stub);
			stub = new Event("jack2",QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1530","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1400","hhmm"), 0);//2-330
			alpha->addCommand(stub);
			QVERIFY(alpha->_entries.currentDisplayIndex==2);//jack2 conflicts with jack1, activeEntries displays jack1 and jack2
			stub = new Task("T1", QDate::fromString("22012014","ddMMyyyy"), QTime::fromString("1200", "hhmm"),0);
			alpha->addCommand(stub);
			stub = new Task("T2", QDate::fromString("27012014","ddMMyyyy"), QTime::fromString("1800", "hhmm"),0);
			alpha->addCommand(stub);
			stub = new Task("T3", QDate::fromString("28012014","ddMMyyyy"), QTime::fromString("0900", "hhmm"),0);
			alpha->addCommand(stub);
			stub = new Task("T5", QDate::fromString("23012014","ddMMyyyy"), QTime::fromString("0900", "hhmm"),0);
			alpha->addCommand(stub);
			stub = new Task("T4", QDate::fromString("29012014","ddMMyyyy"), QTime::fromString("0900", "hhmm"),0);
			alpha->addCommand(stub);
			stub = new Task("T4", QDate::fromString("29012014","ddMMyyyy"), QTime::fromString("0900", "hhmm"),0);
			QVERIFY(alpha->_entries.currentDisplayIndex==7);//displayed conflict from the 3rd entry, jack is not in activevector
			alpha->displayCommand();//displays all
			QVERIFY(alpha->_entries.currentDisplayIndex == 8);//8 entries, should have 8 entries.
		}
		void testDelete() {
			//EntriesManager alpha;
			alpha->deleteCommand(1);//jack1 is deleted, after sorting jack1 is at top, earliest enddate
			QVERIFY(alpha->_entries.currentDisplayIndex==7);
			string output;
			try{
				alpha->deleteCommand(19);
			}//invalid index
			catch(BotException e) {
				output = (e.what());
			}
			QVERIFY(output == "INVALID INDEX");
			output.clear();
			try{
				alpha->deleteCommand(0);
			}//invalid index
			catch(BotException e) {
				output = (e.what());
			}
			QVERIFY(output == "INVALID INDEX");
		}
		void testSearchUpToDate() {
			//EntriesManager alpha;
			alpha->searchDay(QDate::fromString("23012014", "ddMMyyyy"),1);
			QVERIFY(alpha->_entries.currentDisplayIndex==4);//index is 4
		}
		void testSearchName() {
			alpha->searchCommand("jack2", 1);
			QVERIFY(alpha->_entries.currentDisplayIndex==1);
			alpha->displayCommand();
			QVERIFY(alpha->_entries.currentDisplayIndex==7);
			alpha->searchCommand("asdasd", 1);
			QVERIFY(alpha->_entries.currentDisplayIndex==0);
		}
		void testSearchAttributes() {
			//Equivalence partitioning for terms within the existing entries
			//terms outside the existing partitions
			alpha->displayCommand();
			alpha->searchCommand("27/1");//only T2 should be displayed
			QVERIFY(alpha->_entries.currentDisplayIndex==1);
			alpha->displayCommand();
			alpha->searchCommand("27/1 jack");//jacks and T2 should be displayed
			QVERIFY(alpha->_entries.currentDisplayIndex==3);//contains terms within existing entries
			alpha->displayCommand();
			alpha->searchCommand("27/1 jak");//only T2 should be displayed
			QVERIFY(alpha->_entries.currentDisplayIndex==1);//contains terms outside existing entries
			alpha->displayCommand();
			QVERIFY(alpha->_entries.currentDisplayIndex==7);
			alpha->displayCommand();
			alpha->searchCommand("jack has");//all words searched individually, jacks should be returned
			QVERIFY(alpha->_entries.currentDisplayIndex==2);
		}
		void testUndo() {//9 actions so far
			alpha->undoCommand();//at this point index is 2, hence when redo called, is index 2
			QVERIFY(alpha->_entries.currentDisplayIndex==8);
			string output;
			try{
				for(int i=0; i<10; i++)
					alpha->undoCommand();
			}
			catch(BotException e) {
				output = e.what();
			}
			QVERIFY(output=="INVALID UNDO");
		}
		void testRedo() {
			string output;
			for(int i=0; i<10; i++)
				alpha->redoCommand();
			QVERIFY(alpha->_entries.currentDisplayIndex==2);
			try{
				alpha->redoCommand();
			}
			catch(BotException e) {
				output = e.what();
			}
			QVERIFY(output == "INVALID REDO");
		}
		void testUndoLimit() {//current displayindex should be 2 here, since last redo. UNDO LIMIT:10
			//undo attempts
			//0. within range (1-9) as demonstrated above
			//1. equal to max attempt = 10
			//2. exceed range >=11
			alpha->clearCommand();//1 action
			for(int i=0; i<9; i++) {//9 actions here
				Entry* stub = new Event();
				alpha->addCommand(stub);
			}//redo stack is emptied
			QVERIFY(alpha->_entries.currentDisplayIndex == 9);// 9 items added
			for(int i=0; i<10; i++) {
				alpha->undoCommand();
			}//10 undos
			QVERIFY(alpha->_entries.currentDisplayIndex == 2);//undo until clearcommand
			for(int i=0; i<10; i++) {
				alpha->redoCommand();
			}//10 redos
			QVERIFY(alpha->_entries.currentDisplayIndex == 9);
			string output;
			try{
				for(int i=0; i<11; i++) {
					alpha->undoCommand();
				}//11 undos, should return invalid exception since only 10 undos allowed
			}
			catch(BotException e) {
				output = e.what();
			}
			QVERIFY(output=="INVALID UNDO");
		}

};
class EntriesManagerTest:public QObject {//tests here involve the actual FileManager and Events/Tasks classes
	Q_OBJECT
private:
	EntriesManager* alpha;
	EntriesManager* alphaOccuring;
	private slots:
		void initTestCase() {
			// Called before all unit tests.

			// Initialize the logging engines
			QxtLoggerEngine *fileLogger = new QxtBasicFileLoggerEngine("test.log");
			QxtLoggerEngine *stdoutLogger = new QxtBasicSTDLoggerEngine();

			qxtLog->addLoggerEngine("file", fileLogger);
			qxtLog->addLoggerEngine("stdout", stdoutLogger);

			qxtLog->disableAllLogLevels();

			qxtLog->enableLogLevels("file", QxtLogger::AllLevels);
			qxtLog->enableLogLevels("stdout", QxtLogger::AllLevels);
			alpha = EntriesManager::getInstance();
		}
		
		void testAdd() {
			//EntriesManager alpha;
			Entry* stub;
			alpha->clearCommand();
			stub = new Event("jack",QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1400","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1300","hhmm"), 0);//1-2
			alpha->addCommand(stub);
			stub = new Event("jack1",QDate::fromString("230114","ddMMyy"),QTime::fromString("1430","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1400","hhmm"), 0);//2-230
			alpha->addCommand(stub);
			stub = new Event("jack2",QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1530","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1400","hhmm"), 0);//2-330
			alpha->addCommand(stub);
			QVERIFY(alpha->_entries.currentDisplayIndex==2);//jack2 conflicts with jack1, activeEntries displays jack1 and jack2
			stub = new Task("T1", QDate::fromString("22012014","ddMMyyyy"), QTime::fromString("1200", "hhmm"),0);
			alpha->addCommand(stub);
			stub = new Task("T2", QDate::fromString("27012014","ddMMyyyy"), QTime::fromString("1800", "hhmm"),0);
			alpha->addCommand(stub);
			stub = new Task("T3", QDate::fromString("28012014","ddMMyyyy"), QTime::fromString("0900", "hhmm"),0);
			alpha->addCommand(stub);
			stub = new Task("T5", QDate::fromString("29012014","ddMMyyyy"), QTime::fromString("0900", "hhmm"),0);
			alpha->addCommand(stub);
			stub = new Task("T4", QDate::fromString("23012014","ddMMyyyy"), QTime::fromString("0900", "hhmm"),0);
			alpha->addCommand(stub);
			QVERIFY(alpha->_entries.currentDisplayIndex==7);
			alpha->displayCommand();//displays all
			QVERIFY(alpha->_entries.currentDisplayIndex == 8);//8 entries added, should have 8 entries.
		}
		void testDelete() {
			//EntriesManager alpha;
			alpha->deleteCommand(1);//jack1 is deleted, after sorting jack1 is at top, earliest enddate
			QVERIFY(alpha->_entries.currentDisplayIndex==7);
			string output;
			try{
				alpha->deleteCommand(19);
			}//invalid index
			catch(BotException e) {
				output = (e.what());
			}
			QVERIFY(output == "INVALID INDEX");
			output.clear();
			try{
				alpha->deleteCommand(0);
			}//invalid index
			catch(BotException e) {
				output = (e.what());
			}
			QVERIFY(output == "INVALID INDEX");
		}
		void testSearchUpToDate() {
			//EntriesManager alpha;
			alpha->searchDay(QDate::fromString("23012014", "ddMMyyyy"),1);
			QVERIFY(alpha->_entries.currentDisplayIndex==4);//index is 4
		}
		void testSearchName() {
			alpha->searchCommand("jack2", 1);
			QVERIFY(alpha->_entries.currentDisplayIndex==1);
			alpha->displayCommand();
			QVERIFY(alpha->_entries.currentDisplayIndex==7);
			alpha->searchCommand("asdasd", 1);
			QVERIFY(alpha->_entries.currentDisplayIndex==0);
		}
		void testSearchAttributes() {
			alpha->displayCommand();
			alpha->searchCommand("27/1");//only T2 should be displayed
			QVERIFY(alpha->_entries.currentDisplayIndex==1);
			alpha->displayCommand();
			QVERIFY(alpha->_entries.currentDisplayIndex==7);
			alpha->displayCommand();
			alpha->searchCommand("jack");//all words searched individually, jacks should be returned
			QVERIFY(alpha->_entries.currentDisplayIndex==2);
		}
		void testUndo() {//9 actions so far
			alpha->undoCommand();//at this point index is 2, hence when redo called, is index 2
			QVERIFY(alpha->_entries.currentDisplayIndex==8);
			string output;
			try{
				for(int i=0; i<10; i++)
					alpha->undoCommand();
			}
			catch(BotException e) {
				output = e.what();
			}
			QVERIFY(output=="INVALID UNDO");
		}
		void testRedo() {
			string output;
			for(int i=0; i<10; i++)
				alpha->redoCommand();
			QVERIFY(alpha->_entries.currentDisplayIndex==2);
			try{
				alpha->redoCommand();
			}
			catch(BotException e) {
				output = e.what();
			}
			QVERIFY(output == "INVALID REDO");
		}
		void testgetConflict() {
			//new events are either
			//1. lie across and exceed range of multiple old events
			//2. out of range of old event ranges
			//3. lie within range of one single event
			//4. lie within range of multiple old events
			//5. lie in exact same range of 1 old event
			//6. lie in exact same range of more than 1 old event
			alpha->displayCommand();
			QVERIFY(alpha->_entries.currentDisplayIndex==7);
			Entry* stub = new Event("Conflict", QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1630","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1200","hhmm"), 0);//12-430, should clash with 1-2, 2-230
			vector<Entry*> temp = alpha->getConflict(stub);//new range encompasses old ranges, 
			//for(int i=0; i<temp.size(); i++)
			//	cout << temp[i]->toString();
			QVERIFY(temp.size()==2);
			delete stub;
			stub = new Event("Conflict", QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1300","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1200","hhmm"), 0);//12-1300, should not clash
			temp = alpha->getConflict(stub);//out of range before
			QVERIFY(temp.size()==0);
			delete stub;
			stub = new Event("Conflict", QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1600","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1330","hhmm"), 0);//1330-1600, should clash with 1-2, 2-230
			temp = alpha->getConflict(stub);//new range is between range of two old ranges
			for(int i=0; i<temp.size(); i++)
				cout << temp[i]->toString();
			QVERIFY(temp.size()==2);
			delete stub;
			stub = new Event("Conflict", QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1400","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1300","hhmm"), 0);//1300-1400, should clash with 1-2
			temp = alpha->getConflict(stub);//exact conflict
			for(int i=0; i<temp.size(); i++)
				cout << temp[i]->toString();
			QVERIFY(temp.size()==1);
			delete stub;
			stub = new Event("Conflict", QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1430","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1300","hhmm"), 0);//1300-1530, should clash with 1-2, 2-230
			temp = alpha->getConflict(stub);//exact clash with two old ranges
			for(int i=0; i<temp.size(); i++)
				cout << temp[i]->toString();
			QVERIFY(temp.size()==2);
			delete stub;
			stub = new Event("Conflict", QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1600","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1530","hhmm"), 0);//1530-1600, should clash with none
			temp = alpha->getConflict(stub);//out of range after
			for(int i=0; i<temp.size(); i++)
				cout << temp[i]->toString();
			QVERIFY(temp.size()==0);
		}

		void testUndoLimit() {//current displayindex should be 2 here, since last redo. UNDO LIMIT:10
			//undo attempts
			//0. within range (1-9) as demonstrated above
			//1. equal to max attempt = 10
			//2. exceed range >=11
			alpha->clearCommand();//1 action
			for(int i=0; i<9; i++) {//9 actions here
				Entry* stub = new Event();
				alpha->addCommand(stub);
			}//redo stack is emptied
			QVERIFY(alpha->_entries.currentDisplayIndex == 9);// 9 items added
			for(int i=0; i<10; i++) {
				alpha->undoCommand();
			}//10 undos
			QVERIFY(alpha->_entries.currentDisplayIndex == 2);//undo until clearcommand
			for(int i=0; i<10; i++) {
				alpha->redoCommand();
			}//10 redos
			QVERIFY(alpha->_entries.currentDisplayIndex == 9);
			string output;
			try{
				for(int i=0; i<11; i++) {
					alpha->undoCommand();
				}//11 undos, should return invalid exception since only 10 undos allowed
			}
			catch(BotException e) {
				output = e.what();
			}
			QVERIFY(output=="INVALID UNDO");
		}
		/*
		void testgetOccuring() {
			Entry* stub;
			cout<< alpha->_currentDisplayIndex << endl;

			stub = new Event("jack1",QDate::fromString("03042014","ddMMyyyy"),QTime::fromString("1430","hhmm"),
				QDate::fromString("01042014","ddMMyyyy"),QTime::fromString("1400","hhmm"), 0);
			alpha->addCommand(stub);
			QVERIFY(alpha->_currentDisplayIndex==3);
			vector<Entry*> occuring = alpha->getOccuring();
			cout << occuring.size() << endl;
			QVERIFY(occuring.size()==1); //occuring on current date
			delete stub;
		}*/
};
class FileManagerTest : public QObject {
	Q_OBJECT
private:
	private slots:
		void initTestCase() {
			// Called before all unit tests.

			// Initialize the logging engines
			QxtLoggerEngine *fileLogger = new QxtBasicFileLoggerEngine("test.log");
			QxtLoggerEngine *stdoutLogger = new QxtBasicSTDLoggerEngine();

			qxtLog->addLoggerEngine("file", fileLogger);
			qxtLog->addLoggerEngine("stdout", stdoutLogger);

			qxtLog->disableAllLogLevels();

			qxtLog->enableLogLevels("file", QxtLogger::AllLevels);
			qxtLog->enableLogLevels("stdout", QxtLogger::AllLevels);
		}
	/*	void testConflict() {
			Event a("jack",QDate::fromString("230114","ddMMyy"),QTime::fromString("1400","hhmm"),
				QDate::fromString("230114","ddMMyy"),QTime::fromString("1300","hhmm"));
			Event b("jack1",QDate::fromString("230114","ddMMyy"),QTime::fromString("1430","hhmm"),
				QDate::fromString("230114","ddMMyy"),QTime::fromString("1330","hhmm"));
			Event c("jack2",QDate::fromString("230114","ddMMyy"),QTime::fromString("1430","hhmm"),
				QDate::fromString("230114","ddMMyy"),QTime::fromString("1400","hhmm"));
			QVERIFY(b.isConflict(a)==true);
			QVERIFY(a.isConflict(c)==false);
		}*/
		void testCompare() {
			Event a("jack",QDate::fromString("230114","ddMMyy"),QTime::fromString("1400","hhmm"),
				QDate::fromString("230114","ddMMyy"),QTime::fromString("1300","hhmm"), 0);
			Event b("jack1",QDate::fromString("230114","ddMMyy"),QTime::fromString("1430","hhmm"),
				QDate::fromString("230114","ddMMyy"),QTime::fromString("1330","hhmm"), 0);
			Event c("jack2",QDate::fromString("230114","ddMMyy"),QTime::fromString("1400","hhmm"),
				QDate::fromString("230114","ddMMyy"),QTime::fromString("1400","hhmm"), 0);
			QVERIFY(EntryManager::greater(&a,&b)==true);//earlier date first
			QVERIFY(EntryManager::greater(&c,&a)==false);//alphabetical order
		}
		/*void testToString() {
			Task ta("T1", QDate::fromString("23012014","ddMMyyyy"), QTime::fromString("1400", "hhmm"),0);
			Event a("jack",QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1400","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1300","hhmm"));
			string expected="TASK\nNAME: T1\nDUE_DATE: 23012014\nDUE_TIME: 1400\n";
			string actual=ta.toString();
			QVERIFY(expected==actual);
			expected="EVENT\nNAME: jack\nDUE_DATE: 23012014\nDUE_TIME: 1400\nSTART_DATE: 23012014\nSTART_TIME: 1300\n";
			actual = a.toString();
			QVERIFY(expected==actual);
		}
		void testFromString() {
			Task ta("T1", QDate::fromString("23012014","ddMMyyyy"), QTime::fromString("1400", "hhmm"),0);
			Event a("jack",QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1400","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1300","hhmm"));
			Task tb = Task::fromString("NAME: T1\nDUE_DATE: 23012014\nDUE_TIME: 1400\nSTATUS: 0\n");
			Event b=Event::fromString("NAME: jack\nDUE_DATE: 23012014\nDUE_TIME: 1400\nSTART_DATE: 23012014\nSTART_TIME: 1300\n");
			//cout << tb.toString() << endl << ta.toString() << endl;
			QVERIFY(ta==tb);
			QVERIFY(a==b);
		}*/
		void testFileManager() {
			FileManager* file= FileManager::getInstance("ii.txt");
			vector<Entry*> alpha;
			Event a("jack",QDate::fromString("230114","ddMMyy"),QTime::fromString("1400","hhmm"),
				QDate::fromString("230114","ddMMyy"),QTime::fromString("1300","hhmm"), 0);
			Event b("jack1",QDate::fromString("230114","ddMMyy"),QTime::fromString("1430","hhmm"),
				QDate::fromString("230114","ddMMyy"),QTime::fromString("1330","hhmm"), 0);
			Event c("jack2",QDate::fromString("230114","ddMMyy"),QTime::fromString("1430","hhmm"),
				QDate::fromString("230114","ddMMyy"),QTime::fromString("1400","hhmm"), 0);
			Task ta("T1", QDate::fromString("23012014","ddMMyyyy"), QTime::fromString("1400", "hhmm"), 0);
			Task tb("T2", QDate::fromString("24012014","ddMMyyyy"), QTime::fromString("1500", "hhmm"),0);
			Task tc("T3", QDate::fromString("25012014","ddMMyyyy"), QTime::fromString("1600", "hhmm"),0);
			alpha.push_back(&a);
			alpha.push_back(&b);
			alpha.push_back(&c);
			alpha.push_back(&ta);
			alpha.push_back(&tb);
			alpha.push_back(&tc);
			file->updateFromVector(alpha);
			for(int i=0; i<alpha.size(); i++) {
				cout << alpha[i]->toString();
			}
			cout << "\n\nALPHA BETA\n\n";
			vector<Entry*> beta = file->getEntries();
			QVERIFY(alpha.size()==beta.size());
			for(int i=0; i< alpha.size(); i++) {
				QVERIFY(beta[i]->toString() == alpha[i]->toString());
				//cout << "**" << beta[i]->toString() << "**"<< endl << "**"<< alpha[i]->toString() << "**";
			}
			FileManager* file1= FileManager::getInstance("il.txt");
			file1->updateFromVector(beta);
		}
		void testToString2() {
			Entry* alpha;
			alpha = new Event("jack",QDate::fromString("230114","ddMMyy"),QTime::fromString("1400","hhmm"),
				QDate::fromString("230114","ddMMyy"),QTime::fromString("1300","hhmm"), 0);
			cout << alpha->toString();
			delete alpha;
			alpha = new Task("T1", QDate::fromString("23012014","ddMMyyyy"), QTime::fromString("1400", "hhmm"),0);
			cout << alpha->toString();
		}
		void testEntriesort() {
			EntriesManager* alpha;
			alpha = EntriesManager::getInstance();
			Entry *stub;
			alpha->clearCommand();
			stub = new Event("jack",QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1600","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1300","hhmm"), 0);
			alpha->addCommand(stub);
			stub = new Event("jack1",QDate::fromString("230114","ddMMyy"),QTime::fromString("1430","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1330","hhmm"), 0);
			alpha->addCommand(stub);
			stub = new Event("jack2",QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1530","hhmm"),
				QDate::fromString("23012014","ddMMyyyy"),QTime::fromString("1400","hhmm"), 0);
			alpha->addCommand(stub);
			stub = new Task("T1", QDate::fromString("23012014","ddMMyyyy"), QTime::fromString("1200", "hhmm"),0);
			alpha->addCommand(stub);
			stub = new Task("T2", QDate::fromString("23012014","ddMMyyyy"), QTime::fromString("1800", "hhmm"),0);
			alpha->addCommand(stub);
			stub = new Task("T3", QDate::fromString("23012014","ddMMyyyy"), QTime::fromString("0900", "hhmm"),0);
			alpha->addCommand(stub);
			stub = new Task("T5", QDate::fromString("23012014","ddMMyyyy"), QTime::fromString("0900", "hhmm"),0);
			alpha->addCommand(stub);
			stub = new Task("T4", QDate::fromString("23012014","ddMMyyyy"), QTime::fromString("0900", "hhmm"),0);
			alpha->addCommand(stub);
			/*
			cout << alpha->displayCommand().displayMsg << endl << "ALPHABETA" << endl << endl;
			cout << alpha->sortCommand().displayMsg  << endl << "ALPHABETA" << endl << endl;
			//alpha->deleteCommand(2);
			cout << alpha->displayCommand().displayMsg << endl << "ALPHABETA" << endl << endl;
			alpha->undoCommand();
			cout << alpha->displayCommand().displayMsg << endl << "ALPHABETA" << endl << endl;
			alpha->undoCommand();
			alpha->undoCommand();
			alpha->undoCommand();
			alpha->undoCommand();
			cout << alpha->displayCommand().displayMsg << endl << "ALPHABETA" << endl << endl;
			cout << alpha->searchCommand("jack").displayMsg << endl;*/
			alpha->clearCommand();
			alpha->undoCommand();
			//int x;
			/*while(cin >> x) {
				if(x==1) {
					alpha->deleteCommand(1);
					cout << alpha->displayCommand().displayMsg << endl << "ALPHABETA" << endl << endl;
				}else if (x==2) {
					alpha->undoCommand();
					cout << alpha->displayCommand().displayMsg << endl << "ALPHABETA" << endl << endl;
				} else
					break;
				}*/
		}
		// Unit Test END
};
class EntryTest:public QObject {
	Q_OBJECT
private:
	private slots:
		void initTestCase() {
			// Called before all unit tests.
			// Initialize the logging engines
			QxtLoggerEngine *fileLogger = new QxtBasicFileLoggerEngine("test.log");
			QxtLoggerEngine *stdoutLogger = new QxtBasicSTDLoggerEngine();

			qxtLog->addLoggerEngine("file", fileLogger);
			qxtLog->addLoggerEngine("stdout", stdoutLogger);

			qxtLog->disableAllLogLevels();

			qxtLog->enableLogLevels("file", QxtLogger::AllLevels);
			qxtLog->enableLogLevels("stdout", QxtLogger::AllLevels);
		}

		/*void testOngoingOrNot() { //ongoing case
			Entry* stub;
			stub = new Event("Jill",QDate::fromString("23032014","ddMMyyyy"),QTime::fromString("1400","hhmm"),
			QDate::fromString("30032014","ddMMyyyy"),QTime::fromString("1300","hhmm"), 0);
			QVERIFY(stub->isOngoingOrNot() == true );
		}

		void testOngoingOrNot2() { //not ongoing case ()
			Entry* stub;
			stub =  new Event("Julia",QDate::fromString("23022014","ddMMyyyy"),QTime::fromString("1400","hhmm"),
			QDate::fromString("30022014","ddMMyyyy"),QTime::fromString("1300","hhmm"), 0);
			QVERIFY(stub->isOngoingOrNot() == false);
		}
		void testOngoingOrNot3(){ //not ongoing border case (past event)
			Entry* stub;
			stub =  new Event("Jane",QDate::fromString("27032014","ddMMyyyy"),QTime::fromString("1400","hhmm"),
			QDate::fromString("28032014","ddMMyyyy"),QTime::fromString("1200","hhmm"), 0);
			QVERIFY(stub->isOngoingOrNot() == false);
		}
		void testOngoingOrNot4(){ //not ongoing border case (future event)
			Entry* stub;
			stub =  new Event("July",QDate::fromString("28032014","ddMMyyyy"),QTime::fromString("1300","hhmm"),
			QDate::fromString("28032014","ddMMyyyy"),QTime::fromString("1500","hhmm"), 0);
			QVERIFY(stub->isOngoingOrNot() == false);
		}
		void testOngoingOrNot5(){ //not ongoing border case (with invalid dates)
			Entry* stub;
			stub =  new Event("Jenny",QDate::fromString("30022014","ddMMyyyy"),QTime::fromString("1300","hhmm"),
			QDate::fromString("31042014","ddMMyyyy"),QTime::fromString("1500","hhmm"), 0);
			QVERIFY(stub->isOngoingOrNot() == false);
		}
		void testOngoingOrNot6(){ //not ongoing border case (with invalid time)
			Entry* stub;
			stub =  new Event("Jenny",QDate::fromString("28022014","ddMMyyyy"),QTime::fromString("2500","hhmm"),
			QDate::fromString("30042014","ddMMyyyy"),QTime::fromString("1560","hhmm"), 0);
			QVERIFY(stub->isOngoingOrNot() == false);
		}

		void testgetStatusString1(){ //valid case for Not Done
			Entry* stub;
			stub =  new Event("July",QDate::fromString("28032014","ddMMyyyy"),QTime::fromString("1300","hhmm"),
			QDate::fromString("28032014","ddMMyyyy"),QTime::fromString("1500","hhmm"), 0);
			QVERIFY(stub->getStatusString() == "Not Done");
		}

		void testGetStatusString2() { //valid case for Done
			Entry* stub;
			stub = new Event("Jill",QDate::fromString("23022014","ddMMyyyy"),QTime::fromString("1400","hhmm"),
			QDate::fromString("25022014","ddMMyyyy"),QTime::fromString("1300","hhmm"), 1);
			QVERIFY(stub->getStatusString() == "Done");
		}

		void testGetStatusString3(){ //not ongoing border case (invalid boolean value)
			Entry* stub;
			string output;
			try{
			stub =  new Event("Jane",QDate::fromString("27032014","ddMMyyyy"),QTime::fromString("1400","hhmm"),
			QDate::fromString("28032014","ddMMyyyy"),QTime::fromString("1200","hhmm"), 3);
			stub->getStatusString();
			}//invalid status
			catch(BotException e){
			output = (e.what());
			}
			QVERIFY(output == "INVALID INDEX");
		}*/
		void testDateTime() {
			cout << (QDateTime(QDate::currentDate(), QTime()).isValid()) << endl;
		}
		void testGetStartDate(){
			QDate StartDate(2014, 4, 1);
			QVERIFY(StartDate.isValid());
		}
		void testIsOccuring1(){
			QDate current = QDate::currentDate();
			Entry* stub;
			//QDate current = QDate::fromString("01042014", "ddmmyyyy");
			stub = new Event("Jane",QDate::fromString("01042014","ddMMyyyy"),QTime::fromString("1400","hhmm"),
			QDate::fromString("01042014","ddMMyyyy"),QTime::fromString("1200","hhmm"), 0);
			QString curStr = current.toString();
			QDate startStr = stub->getStartDate();
			QString strStr = startStr.toString();
			//cout << curStr.toUtf8().constData() << endl << strStr.toUtf8().constData() << endl;
			//QVERIFY(current == startStr);
			QVERIFY(stub->isOccuring(current) == true);
		}
		void testIsOccuring2(){
			QDate current = QDate::currentDate();
			Entry* stub;
			//QDate current = QDate::fromString("01042014", "ddmmyyyy");
			stub = new Event("Jane",QDate::fromString("03042014","ddMMyyyy"),QTime::fromString("1400","hhmm"),
			QDate::fromString("01042014","ddMMyyyy"),QTime::fromString("1200","hhmm"), 0);
			QString curStr = current.toString();
			QDate startStr = stub->getStartDate();
			QString strStr = startStr.toString();
			//cout << curStr.toUtf8().constData() << endl << strStr.toUtf8().constData() << endl;
			//QVERIFY(current == startStr);
			QVERIFY(stub->isOccuring(current) == true);
		}
};


//QTEST_MAIN(EntriesManagerUTest);
QTEST_MAIN(EntriesManagerTest);
//QTEST_MAIN(FileManagerTest);
//QTEST_MAIN(EntryTest);
#include "main.moc"